import tkinter as tk
from tkinter import ttk, scrolledtext
import time
import threading
from typing import Callable, Dict, Any, List
import sys
import os

# 添加项目路径到sys.path
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)

from models.factory import ModelFactory
from .discussion_dialog import DiscussionDialog
from utils.cache_manager import cache_manager
from utils.context_manager import context_manager


class ChatTab:
    """聊天界面标签页"""
    
    def __init__(self, parent_frame, models: dict, config_manager=True):
        self.parent_frame = parent_frame
        self.models = models
        self.config_manager = config_manager
        self.root = parent_frame.winfo_toplevel()  # 获取顶级窗口引用
        
        # 初始化模型工厂
        self.model_factory = ModelFactory()
        self.current_model_instance = None
        self.current_model_name = None
        
        # 初始化变量
        self.thinking_counter = 0
        self.is_typing = False
        self.chat_history = []  # 存储当前对话历史
        self.current_role_system_prompt = None  # 存储当前角色的系统提示词
        
        # 缓存相关
        self.enable_caching = True  # 是否启用响应缓存
        
        # 上下文管理相关
        self.max_context_tokens = 4000  # 最大上下文token数
        self.max_context_messages = 20   # 最大上下文消息数
        
        # 回调函数
        self.on_send = None
        self.on_model_change = None
        self.on_thinking_change = None
        self.on_clear_chat = None
        self.on_role_change = None
        self.on_start_discussion = None  # 新增讨论回调
        
        # 设置界面
        self.setup_chat_interface()
    
    def setup_chat_interface(self):
        """设置聊天界面"""
        self.parent_frame.columnconfigure(0, weight=1)
        self.parent_frame.rowconfigure(0, weight=1)
        
        # 聊天显示区域
        chat_display_frame = ttk.Frame(self.parent_frame)
        chat_display_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        chat_display_frame.columnconfigure(0, weight=1)
        chat_display_frame.rowconfigure(0, weight=1)
        
        self.chat_display = scrolledtext.ScrolledText(
            chat_display_frame,
            wrap=tk.WORD,
            width=70,
            height=30,
            font=('Microsoft YaHei', 10),
            padx=10,
            pady=10,
            bg='white',
            fg='black',
            selectbackground='#c8c8c8',
            insertbackground='black',
            relief=tk.FLAT,
            borderwidth=1,
            state=tk.DISABLED
        )
        self.chat_display.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        self.setup_chat_styles()
        
        # 输入区域
        input_frame = ttk.Frame(self.parent_frame)
        input_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        input_frame.columnconfigure(0, weight=1)
        
        self.input_text = tk.Text(
            input_frame,
            height=3,
            wrap=tk.WORD,
            font=('Arial', 10)
        )
        self.input_text.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 10))
        
        # 发送按钮
        self.send_button = ttk.Button(
            input_frame,
            text="发送",
            command=self._on_send_click
        )
        self.send_button.grid(row=0, column=1)
        
        # 绑定回车键
        self.input_text.bind('<Return>', self._on_enter_key)
        self.input_text.bind('<Control-Return>', lambda e: self._on_send_click())
        self.input_text.bind('<Shift-Return>', self._on_shift_enter)
        
        # 控制区域
        self.setup_control_area()
        
        # 初始化默认模型
        self.root.after(100, self.initialize_model)
    
    def setup_chat_styles(self):
        """设置聊天样式"""
        # 配置标签样式
        self.chat_display.tag_configure("user", foreground="#333333", justify=tk.RIGHT, rmargin=20)
        self.chat_display.tag_configure("ai", foreground="#2B6DAB", justify=tk.LEFT, lmargin1=20, lmargin2=20)
        self.chat_display.tag_configure("system", foreground="#666666", justify=tk.CENTER)
        self.chat_display.tag_configure("timestamp", foreground="#666666", spacing1=10)
        
        # 用户消息样式 - 右对齐，气泡式背景
        self.chat_display.tag_configure("user_message", 
                                       foreground="#333333", 
                                       justify=tk.RIGHT, 
                                       lmargin1=100, lmargin2=100, rmargin=10,
                                       background="#E8F8E8", 
                                       relief=tk.SOLID, 
                                       borderwidth=1,
                                       spacing1=8, spacing3=8,
                                       bgstipple="")
        self.chat_display.tag_configure("user_label", 
                                       foreground="#1976d2", 
                                       justify=tk.RIGHT, 
                                       lmargin1=100, lmargin2=100, rmargin=10,
                                       font=('Microsoft YaHei', 9, 'bold'))
        
        # AI消息样式 - 左对齐，气泡式背景
        self.chat_display.tag_configure("ai_message", 
                                       foreground="#2B6DAB", 
                                       justify=tk.LEFT, 
                                       lmargin1=10, lmargin2=10, rmargin=100,
                                       background="#E8F4FD", 
                                       relief=tk.SOLID, 
                                       borderwidth=1,
                                       spacing1=8, spacing3=8,
                                       bgstipple="")
        self.chat_display.tag_configure("ai_label", 
                                       foreground="#2B6DAB", 
                                       justify=tk.LEFT, 
                                       lmargin1=10, lmargin2=10, rmargin=100,
                                       font=('Microsoft YaHei', 9, 'bold'))
        
        # 系统消息样式 - 居中，气泡式背景
        self.chat_display.tag_configure("system_message", 
                                       foreground="#666666", 
                                       justify=tk.CENTER, 
                                       lmargin1=50, lmargin2=50, rmargin=50,
                                       background="#FFF3CD", 
                                       relief=tk.SOLID, 
                                       borderwidth=1,
                                       spacing1=8, spacing3=8,
                                       bgstipple="")
        self.chat_display.tag_configure("system_label", 
                                       foreground="#856404", 
                                       justify=tk.CENTER, 
                                       lmargin1=50, lmargin2=50, rmargin=50,
                                       font=('Microsoft YaHei', 9, 'bold'))
        
        # 配置markdown样式
        self.setup_markdown_styles()
        
        # 配置思考过程相关标签样式
        self.setup_thinking_styles()
    
    def setup_markdown_styles(self):
        """设置Markdown样式"""
        self.chat_display.tag_configure("markdown_h1", font=('Microsoft YaHei', 14, 'bold'), foreground="#1a1a1a", spacing1=10, spacing3=5)
        self.chat_display.tag_configure("markdown_h2", font=('Microsoft YaHei', 13, 'bold'), foreground="#1a1a1a", spacing1=8, spacing3=4)
        self.chat_display.tag_configure("markdown_h3", font=('Microsoft YaHei', 12, 'bold'), foreground="#1a1a1a", spacing1=6, spacing3=3)
        self.chat_display.tag_configure("markdown_bold", font=('Microsoft YaHei', 10, 'bold'))
        self.chat_display.tag_configure("markdown_italic", font=('Microsoft YaHei', 10, 'italic'))
        self.chat_display.tag_configure("markdown_code", font=('Consolas', 9), background="#f5f5f5", foreground="#d63384")
        self.chat_display.tag_configure("markdown_code_block", font=('Consolas', 9), background="#f8f9fa", foreground="#212529", lmargin1=20, lmargin2=20, spacing1=5, spacing3=5)
        self.chat_display.tag_configure("markdown_quote", font=('Microsoft YaHei', 10, 'italic'), foreground="#6c757d", lmargin1=20, lmargin2=20, spacing1=3, spacing3=3)
        self.chat_display.tag_configure("markdown_list", lmargin1=20, lmargin2=30)
    
    def setup_thinking_styles(self):
        """设置思考过程样式"""
        self.chat_display.tag_configure("thinking", foreground="#666666")
        self.chat_display.tag_configure("thinking_toggle", foreground="#2B6DAB", underline=True)
        self.chat_display.tag_configure("thinking_section", foreground="#666666", lmargin1=20, lmargin2=20, spacing1=5, spacing2=5, elide=False)
        
        # 绑定点击事件
        self.chat_display.tag_bind("thinking_toggle", "<Button-1>", self.toggle_thinking_visibility)
        self.chat_display.tag_bind("thinking_toggle", "<Enter>", lambda e: self.chat_display.config(cursor="hand2"))
        self.chat_display.tag_bind("thinking_toggle", "<Leave>", lambda e: self.chat_display.config(cursor=""))
    
    def setup_control_area(self):
        """设置控制区域"""
        control_frame = ttk.Frame(self.parent_frame)
        control_frame.grid(row=2, column=0, sticky=(tk.W, tk.E))
        control_frame.columnconfigure(1, weight=1)
        
        # 第一行：模型选择和角色选择
        # 模型选择
        ttk.Label(control_frame, text="选择模型:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))
        self.model_var = tk.StringVar()
        
        # 从配置文件获取模型列表
        model_names = []
        if self.config_manager:
            model_names = self.config_manager.get_model_names()
        
        model_combo = ttk.Combobox(control_frame, textvariable=self.model_var, values=model_names, state="readonly", width=15)
        model_combo.grid(row=0, column=1, sticky=tk.W, padx=(0, 10))
        model_combo.bind('<<ComboboxSelected>>', lambda e: self._on_model_change())
        
        # 设置当前模型
        if self.config_manager:
            current_model = self.config_manager.get_current_model_from_config()
            if current_model and current_model in model_names:
                self.model_var.set(current_model)
            elif model_names:
                self.model_var.set(model_names[0])
        
        # 角色选择
        ttk.Label(control_frame, text="选择角色:").grid(row=0, column=2, sticky=tk.W, padx=(10, 5))
        self.role_var = tk.StringVar()
        self.role_combo = ttk.Combobox(control_frame, textvariable=self.role_var, state="readonly", width=15)
        self.role_combo.grid(row=0, column=3, sticky=tk.W, padx=(0, 10))
        self.role_combo.bind('<<ComboboxSelected>>', lambda e: self._on_role_change())
        
        # 更新角色列表
        self._update_role_list()
        
        # 第二行：深度思考开关和清空聊天按钮
        # 深度思考开关
        self.thinking_var = tk.BooleanVar(value=False)
        thinking_check = ttk.Checkbutton(control_frame, text="深度思考", variable=self.thinking_var, command=self._on_thinking_change)
        thinking_check.grid(row=1, column=0, sticky=tk.W, pady=(5, 0))
        
        # 清空聊天按钮
        clear_button = ttk.Button(control_frame, text="清空聊天", command=self._on_clear_chat)
        clear_button.grid(row=1, column=1, sticky=tk.W, padx=(10, 0), pady=(5, 0))
        
        # 讨论按钮
        discussion_button = ttk.Button(control_frame, text="讨论", command=self._on_discussion_click)
        discussion_button.grid(row=1, column=2, sticky=tk.W, padx=(10, 0), pady=(5, 0))
        
        # 第三行：上下文管理设置
        context_frame = ttk.Frame(control_frame)
        context_frame.grid(row=2, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=(10, 0))
        
        # 上下文缓存开关
        self.context_cache_var = tk.BooleanVar(value=True)
        cache_check = ttk.Checkbutton(context_frame, text="上下文缓存", variable=self.context_cache_var, 
                                     command=self._on_context_cache_toggle)
        cache_check.grid(row=0, column=0, sticky=tk.W, padx=(0, 15))
        
        # 上下文token限制
        ttk.Label(context_frame, text="最大上下文:").grid(row=0, column=1, sticky=tk.W, padx=(0, 5))
        self.max_context_tokens_var = tk.IntVar(value=self.max_context_tokens)
        tokens_spin = ttk.Spinbox(context_frame, from_=1000, to=16000, increment=1000, 
                                 textvariable=self.max_context_tokens_var, width=8,
                                 command=self._on_max_tokens_change)
        tokens_spin.grid(row=0, column=2, sticky=tk.W, padx=(0, 10))
        ttk.Label(context_frame, text="tokens").grid(row=0, column=3, sticky=tk.W, padx=(0, 15))
        
        # 上下文消息限制
        ttk.Label(context_frame, text="最大消息数:").grid(row=0, column=4, sticky=tk.W, padx=(0, 5))
        self.max_context_messages_var = tk.IntVar(value=self.max_context_messages)
        messages_spin = ttk.Spinbox(context_frame, from_=5, to=50, increment=5, 
                                   textvariable=self.max_context_messages_var, width=5,
                                   command=self._on_max_messages_change)
        messages_spin.grid(row=0, column=5, sticky=tk.W, padx=(0, 5))
        ttk.Label(context_frame, text="条").grid(row=0, column=6, sticky=tk.W)
    
    def _update_role_list(self):
        """更新角色列表"""
        if self.config_manager:
            # 从配置文件获取角色列表
            role_names = self.config_manager.get_role_names_from_config()
            self.role_combo['values'] = role_names
            
            # 设置当前角色
            current_role = self.config_manager.get_current_role_from_config()
            if current_role in role_names:
                self.role_var.set(current_role)
            elif role_names:
                self.role_var.set(role_names[0])
    
    def _on_role_change(self):
        """角色切换事件"""
        selected_role = self.role_var.get()
        # self.add_message(f"[调试] 尝试切换到角色: {selected_role}", "system")
        if selected_role:
            # 显示角色切换消息
            self.add_message(f"已切换到角色: {selected_role}", "system")
            
            # 设置角色对应的系统提示词
            if self.config_manager:
                # self.add_message(f"[调试] 正在从配置管理器获取角色配置", "system")
                role_config = self.config_manager.get_role_config(selected_role)
                # self.add_message(f"[调试] 获取到的角色配置: {role_config}", "system")
                if role_config and 'system_prompt' in role_config:
                    # 更新当前会话的系统提示词
                    self.current_role_system_prompt = role_config['system_prompt']
                    self.add_message(f"[调试] 提示词已更新为: {self.current_role_system_prompt}","system")
                else:
                    self.add_message(f"[调试] 未找到角色 '{selected_role}' 的系统提示词", "system")
            else:
                self.add_message(f"[调试] 配置管理器不可用", "system")
        else:
            self.add_message(f"[调试] 未选择角色", "system")
        if self.on_role_change:
            self.on_role_change()
    
    def get_role_var(self):
        """获取角色变量"""
        return self.role_var
    
    def create_message_bubble(self, text: str, role: str):
        """创建消息气泡效果，根据文字长度和高度调整背景"""
        # 计算文字行数和最大行长度
        lines = text.split('\n')
        max_line_length = max(len(line) for line in lines) if lines else 0
        line_count = len(lines)
        
        # 根据角色和文字长度动态调整边距
        if role == "user":
            # 用户消息：右对齐，根据文字长度调整左边距
            if max_line_length < 20:
                lmargin = 200  # 短消息，更靠右
            elif max_line_length < 40:
                lmargin = 150  # 中等消息
            else:
                lmargin = 100  # 长消息，给更多空间
            
            tag_name = f"user_bubble_{hash(text) % 10000}"
            self.chat_display.tag_configure(tag_name,
                                          foreground="#333333",
                                          justify=tk.RIGHT,
                                          lmargin1=lmargin, lmargin2=lmargin, rmargin=15,
                                          background="#E8F8E8",
                                          relief=tk.SOLID,
                                          borderwidth=1,
                                          spacing1=6, spacing3=6)
            
        elif role == "assistant":
            # AI消息：左对齐，根据文字长度调整右边距
            if max_line_length < 20:
                rmargin = 200  # 短消息，更靠左
            elif max_line_length < 40:
                rmargin = 150  # 中等消息
            else:
                rmargin = 100  # 长消息，给更多空间
            
            tag_name = f"ai_bubble_{hash(text) % 10000}"
            self.chat_display.tag_configure(tag_name,
                                          foreground="#2B6DAB",
                                          justify=tk.LEFT,
                                          lmargin1=15, lmargin2=15, rmargin=rmargin,
                                          background="#E8F4FD",
                                          relief=tk.SOLID,
                                          borderwidth=1,
                                          spacing1=6, spacing3=6)
        else:
            # 系统消息：居中
            tag_name = f"system_bubble_{hash(text) % 10000}"
            self.chat_display.tag_configure(tag_name,
                                          foreground="#666666",
                                          justify=tk.CENTER,
                                          lmargin1=80, lmargin2=80, rmargin=80,
                                          background="#FFF3CD",
                                          relief=tk.SOLID,
                                          borderwidth=1,
                                          spacing1=6, spacing3=6)
        
        return tag_name
    
    def add_message(self, message: str, role: str, thinking_content: str = None):
        """添加消息到聊天显示区域"""
        self.chat_display.config(state=tk.NORMAL)
        
        # 添加时间戳
        timestamp = time.strftime("%H:%M:%S")
        
        if role == "assistant":
            # AI消息 - 左对齐
            self.chat_display.insert(tk.END, f"[{timestamp}] ", "timestamp")
            self.chat_display.insert(tk.END, "🤖 AI\n", "ai_label")
            
            if thinking_content:
                # 为每个思考过程生成唯一标签
                self.thinking_counter += 1
                thinking_tag = f"thinking_section_{self.thinking_counter}"
                toggle_tag = f"thinking_toggle_{self.thinking_counter}"
                
                # 添加思考过程切换按钮
                self.chat_display.insert(tk.END, "💭 思考过程 ", "thinking")
                self.chat_display.insert(tk.END, "[点击展开]\n", toggle_tag)
                
                # 添加思考过程内容（使用唯一的thinking_section标签）
                thinking_start = self.chat_display.index(tk.END)
                self.chat_display.insert(tk.END, thinking_content + "\n", thinking_tag)
                thinking_end = self.chat_display.index(tk.END)
                
                # 配置思考过程内容样式并默认收起
                self.chat_display.tag_configure(thinking_tag, foreground="#666666", lmargin1=40, lmargin2=40, spacing1=5, spacing2=5, elide=True)
                # 配置切换按钮样式和事件
                self.chat_display.tag_configure(toggle_tag, foreground="#2B6DAB", underline=True, lmargin1=20, lmargin2=20)
                self.chat_display.tag_bind(toggle_tag, "<Button-1>", 
                    lambda e, t_tag=thinking_tag, tog_tag=toggle_tag: self.toggle_specific_thinking_visibility(e, t_tag, tog_tag))
                self.chat_display.tag_bind(toggle_tag, "<Enter>", lambda e: self.chat_display.config(cursor="hand2"))
                self.chat_display.tag_bind(toggle_tag, "<Leave>", lambda e: self.chat_display.config(cursor=""))
            
            # 创建动态气泡样式
            bubble_tag = self.create_message_bubble(message, "assistant")
            # 显示回答内容，支持markdown格式，打字机效果会自己处理文本框的禁用
            self.typewriter_effect_with_markdown(message, bubble_tag)
            return  # 提前返回，避免立即禁用文本框
            
        elif role == "user":
            # 用户消息 - 右对齐
            # 创建右对齐的时间戳标签
            timestamp_tag = f"user_timestamp_{hash(timestamp) % 10000}"
            self.chat_display.tag_configure(timestamp_tag, 
                                          foreground="#666666", 
                                          justify=tk.RIGHT,
                                          rmargin=20,
                                          spacing1=10)
            self.chat_display.insert(tk.END, f"[{timestamp}] ", timestamp_tag)
            self.chat_display.insert(tk.END, "👤 用户\n", "user_label")
            
            # 创建动态气泡样式
            bubble_tag = self.create_message_bubble(message, "user")
            self.chat_display.insert(tk.END, f"{message}\n\n", bubble_tag)
            self.chat_display.see(tk.END)
            self.chat_display.update_idletasks()
            
        elif role == "system":
            # 系统消息 - 居中
            self.chat_display.insert(tk.END, f"[{timestamp}] ", "timestamp")
            self.chat_display.insert(tk.END, "🔧 系统\n", "system_label")
            
            # 创建动态气泡样式
            bubble_tag = self.create_message_bubble(message, "system")
            self.chat_display.insert(tk.END, f"{message}\n\n", bubble_tag)
            self.chat_display.see(tk.END)
            self.chat_display.update_idletasks()
        
        # 最后确保内容完全显示并禁用编辑
        self.chat_display.see(tk.END)
        self.chat_display.update_idletasks()
        self.chat_display.config(state=tk.DISABLED)
    
    def clear_chat(self):
        """清空聊天记录"""
        self.chat_display.config(state=tk.NORMAL)
        self.chat_display.delete(1.0, tk.END)
        self.chat_display.config(state=tk.DISABLED)
        
        # 清空聊天历史
        self.chat_history.clear()
        
        # 重置思考计数器
        self.thinking_counter = 0
    
    def _on_clear_chat(self):
        """清空聊天事件"""
        self.clear_chat()
        if self.on_clear_chat:
            self.on_clear_chat()
    
    def set_callbacks(self, on_send: Callable[[str], None], on_model_change: Callable[[], None], 
                     on_thinking_change: Callable[[], None], on_clear_chat: Callable[[], None],
                     on_role_change: Callable[[], None] = None):
        """设置回调函数"""
        self.on_send = on_send
        self.on_model_change = on_model_change
        self.on_thinking_change = on_thinking_change
        self.on_clear_chat = on_clear_chat
        self.on_role_change = on_role_change
    
    def _on_send_click(self):
        """发送按钮点击事件"""
        if self.is_typing:
            return
        
        message = self.input_text.get(1.0, tk.END).strip()
        if not message:
            return
        
        # 清空输入框
        self.input_text.delete(1.0, tk.END)
        
        # 调用回调函数处理消息发送（避免重复显示用户消息）
        if self.on_send:
            self.on_send(message)
        else:
            # 如果没有回调函数，则直接处理
            self.add_message(message, "user")
            self.chat_history.append({"role": "user", "content": message})
            
            # 检查是否有可用的模型
            if not self.current_model_instance:
                self.add_message("请先选择一个模型", "system")
                return
            
            # 在新线程中获取AI响应
            threading.Thread(target=self._get_ai_response, args=(message,), daemon=True).start()
    
    def _get_ai_response(self, user_message: str):
        """获取AI响应（在后台线程中运行）"""
        try:
            # 检查API密钥
            if not self.current_model_instance:
                self.root.after(0, lambda: self.add_message("没有可用的模型实例", "system"))
                return
            
            # 构建系统提示词
            system_prompt = "你是一个友善的AI助手，请用中文回答问题。"
            
            # 如果有配置管理器，优先获取角色的系统提示词
            if hasattr(self, 'current_role_system_prompt') and self.current_role_system_prompt:
                system_prompt = self.current_role_system_prompt
                self.add_message(f"[调试] 使用角色切换时设置的系统提示词: {system_prompt[:50]}...")
            elif self.config_manager:
                role = self.config_manager.get_setting("role", "助手")
                
                # 优先使用角色配置中的系统提示词
                role_config = self.config_manager.get_role_config(role)
                if role_config and 'system_prompt' in role_config:
                    system_prompt = role_config['system_prompt']
                    self.add_message(f"[调试] 使用角色 '{role}' 的系统提示词: {system_prompt[:50]}...")
                else:
                    # 如果角色配置中没有系统提示词，则使用通用配置
                    system_prompt = self.config_manager.get_setting("system_prompt", system_prompt)
                    if role != "助手":
                        system_prompt = f"你是一个{role}，{system_prompt}"
                    self.add_message(f"[调试] 使用通用系统提示词 (角色: {role}): {system_prompt[:50]}...")
            
            # 检查是否启用深度思考
            enable_thinking = self.thinking_var.get() and self.current_model_instance.supports_thinking
            if enable_thinking:
                system_prompt += " 请在回答前进行深度思考，展示你的思考过程。"
            
            # 构建消息列表（使用上下文管理器优化）
            messages = context_manager.optimize_context(
                self.chat_history, 
                system_prompt,
                message
            )
            
            # 打印调用大模型的参数信息
            self.add_message("\n" + "="*50)
            self.add_message("[大模型调用参数]")
            self.add_message(f"模型名称: {self.current_model_name}")
            self.add_message(f"模型类型: {type(self.current_model_instance).__name__}")
            self.add_message(f"深度思考模式: {enable_thinking}")
            self.add_message(f"消息数量: {len(messages)}")
            self.add_message(f"系统提示词: {system_prompt[:100]}{'...' if len(system_prompt) > 100 else ''}")
            self.add_message("消息列表:")
            for i, msg in enumerate(messages):
                role = msg['role']
                content = msg['content'][:50] + ('...' if len(msg['content']) > 50 else '')
                self.add_message(f"  [{i+1}] {role}: {content}")
            self.add_message("="*50 + "\n")
            
            # 检查缓存
            cached_response = None
            if self.enable_caching:
                cached_response = cache_manager.get(messages, self.current_model_name, enable_thinking)
                if cached_response:
                    self.root.after(0, lambda: self.add_message("[缓存命中] 使用缓存的响应", "system"))
            
            if cached_response:
                # 使用缓存的响应
                self.chat_history.append({"role": "assistant", "content": cached_response})
                self.root.after(0, lambda: self.add_message(cached_response, "assistant"))
            else:
                # 检查是否支持流式输出
                if hasattr(self.current_model_instance, 'supports_streaming') and self.current_model_instance.supports_streaming:
                    # 流式输出模式
                    self.root.after(0, lambda: self._start_streaming_response(messages, enable_thinking))
                else:
                    # 传统阻塞模式
                    response = self.current_model_instance.generate_response(messages, enable_thinking)
                    
                    # 保存到缓存
                    if self.enable_caching:
                        cache_manager.set(messages, self.current_model_name, enable_thinking, response if isinstance(response, str) else response.get("response", ""))
                    
                    # 在主线程中显示响应
                    if isinstance(response, dict) and "thinking" in response:
                        # 有思考过程的响应
                        thinking_process = response["thinking"]
                        result = response["response"]
                        self.chat_history.append({"role": "assistant", "content": result})
                        self.root.after(0, lambda: self.add_message(
                            result, "assistant", thinking_content=thinking_process
                        ))
                    else:
                        # 普通响应
                        self.chat_history.append({"role": "assistant", "content": response})
                        self.root.after(0, lambda: self.add_message(response, "assistant"))
                
        except Exception as e:
            error_msg = f"获取AI响应时出错: {str(e)}"
            self.root.after(0, lambda: self.add_message(error_msg, "system"))
    
    def _start_streaming_response(self, messages: List[Dict[str, str]], enable_thinking: bool = False):
        """启动流式响应处理"""
        # 创建新的线程来处理流式响应
        threading.Thread(
            target=self._handle_streaming_response, 
            args=(messages, enable_thinking),
            daemon=True
        ).start()
    
    def _handle_streaming_response(self, messages: List[Dict[str, str]], enable_thinking: bool = False):
        """处理流式响应"""
        try:
            # 在主线程中显示开始响应的提示
            self.root.after(0, lambda: self._prepare_streaming_display())
            
            # 收集完整的响应内容
            full_response = ""
            
            def stream_callback(chunk: str):
                nonlocal full_response
                full_response += chunk
                # 在主线程中更新显示
                self.root.after(0, lambda: self._update_streaming_display(chunk))
            
            # 调用模型的流式输出方法
            self.current_model_instance.generate_response_stream(
                messages, stream_callback, enable_thinking
            )
            
            # 流式输出完成，保存到聊天历史
            self.chat_history.append({"role": "assistant", "content": full_response})
            
            # 保存到缓存
            if self.enable_caching:
                cache_manager.set(messages, self.current_model_name, enable_thinking, full_response)
            
            # 在主线程中完成显示
            self.root.after(0, lambda: self._finish_streaming_display())
            
        except Exception as e:
            error_msg = f"流式响应处理出错: {str(e)}"
            self.root.after(0, lambda: self.add_message(error_msg, "system"))
    
    def _prepare_streaming_display(self):
        """准备流式显示"""
        self.chat_display.config(state=tk.NORMAL)
        # 添加AI标签
        self.chat_display.insert(tk.END, "\nAI: ", "ai_label")
        # 开始新的消息块
        self.chat_display.insert(tk.END, "", "ai_message")
        self.chat_display.config(state=tk.DISABLED)
        self.is_typing = True
    
    def _update_streaming_display(self, chunk: str):
        """更新流式显示"""
        if not self.is_typing:
            return
            
        self.chat_display.config(state=tk.NORMAL)
        # 插入新的内容到当前消息块
        self.chat_display.insert(tk.END, chunk, "ai_message")
        self.chat_display.see(tk.END)
        self.chat_display.config(state=tk.DISABLED)
    
    def _finish_streaming_display(self):
        """完成流式显示"""
        self.is_typing = False
        self.chat_display.config(state=tk.NORMAL)
        # 确保消息格式正确
        self.chat_display.see(tk.END)
        self.chat_display.config(state=tk.DISABLED)
    
    def _on_enter_key(self, event):
        """Enter键事件"""
        self._on_send_click()
        return 'break'
    
    def _on_shift_enter(self, event):
        """Shift+Enter键事件"""
        return None
    
    def _on_model_change(self):
        """模型改变事件"""
        selected_model = self.model_var.get()
        if selected_model and selected_model in self.models:
            self.current_model_name = selected_model
            try:
                # 创建新的模型实例
                self.current_model_instance = self.model_factory.create_model(self.models[selected_model])
                
                # 更新深度思考开关状态
                if not self.current_model_instance.supports_thinking:
                    self.thinking_var.set(False)
                
                # 显示模型切换消息
                self.add_message(f"已切换到模型: {selected_model}", "system")
                
            except Exception as e:
                self.add_message(f"切换模型失败: {str(e)}", "system")
                
        # 调用原有的回调
        if self.on_model_change:
            self.on_model_change()
    
    def initialize_model(self):
        """初始化默认模型"""
        # 如果已经有选中的模型但没有实例，创建实例
        selected_model = self.model_var.get()
        if selected_model and selected_model in self.models and not self.current_model_instance:
            self._on_model_change()
        elif self.models and not self.current_model_instance:
            # 获取第一个可用模型
            first_model = list(self.models.keys())[0]
            self.model_var.set(first_model)
            self._on_model_change()
    
    def get_current_model_info(self):
        """获取当前模型信息"""
        return {
            "name": self.current_model_name,
            "instance": self.current_model_instance,
            "supports_thinking": self.current_model_instance.supports_thinking if self.current_model_instance else False
        }
    
    def _on_thinking_change(self):
        """思考模式改变事件"""
        if self.on_thinking_change:
            self.on_thinking_change()
    
    def _on_clear_chat(self):
        """清空聊天事件"""
        if self.on_clear_chat:
            self.on_clear_chat()
    
    def toggle_thinking_visibility(self, event):
        """切换思考过程的显示状态（通用方法）"""
        self.chat_display.config(state=tk.NORMAL)
        
        # 获取所有thinking_section标签
        all_tags = self.chat_display.tag_names()
        thinking_tags = [tag for tag in all_tags if tag.startswith("thinking_section_")]
        
        if thinking_tags:
            # 获取第一个thinking_section的状态作为参考
            first_tag = thinking_tags[0]
            try:
                current_elide = bool(self.chat_display.tag_cget(first_tag, "elide"))
            except tk.TclError:
                current_elide = True
            
            # 切换所有thinking_section的状态
            new_elide = not current_elide
            for tag in thinking_tags:
                self.chat_display.tag_configure(tag, elide=new_elide)
        
        self.chat_display.config(state=tk.DISABLED)
    
    def toggle_specific_thinking_visibility(self, event, thinking_tag, toggle_tag):
        """切换特定思考过程的显示状态"""
        self.chat_display.config(state=tk.NORMAL)
        
        try:
            # 获取点击的位置
            click_index = self.chat_display.index(f"@{event.x},{event.y}")
            
            # 获取特定切换按钮的范围
            toggle_ranges = self.chat_display.tag_ranges(toggle_tag)
            
            if not toggle_ranges:
                return
            
            for i in range(0, len(toggle_ranges), 2):
                toggle_start = toggle_ranges[i]
                toggle_end = toggle_ranges[i + 1]
                
                # 检查点击是否在当前切换按钮范围内
                if self.chat_display.compare(click_index, ">=", toggle_start) and \
                   self.chat_display.compare(click_index, "<=", toggle_end):
                    
                    # 获取当前特定thinking_section的状态
                    try:
                        current_elide = bool(self.chat_display.tag_cget(thinking_tag, "elide"))
                    except tk.TclError:
                        current_elide = True
                    
                    if current_elide:
                        # 当前是隐藏状态，需要显示
                        self.chat_display.tag_configure(thinking_tag, elide=False)
                        new_text = "[点击收起]"
                    else:
                        # 当前是显示状态，需要隐藏
                        self.chat_display.tag_configure(thinking_tag, elide=True)
                        new_text = "[点击展开]"
                    
                    # 更新切换按钮文本
                    self.chat_display.delete(toggle_start, toggle_end)
                    self.chat_display.insert(toggle_start, new_text, toggle_tag)
                    
                    # 重新绑定事件处理器
                    import functools
                    click_handler = functools.partial(self.toggle_specific_thinking_visibility,
                                                    thinking_tag=thinking_tag,
                                                    toggle_tag=toggle_tag)
                    
                    self.chat_display.tag_bind(toggle_tag, "<Button-1>", click_handler)
                    self.chat_display.tag_bind(toggle_tag, "<Enter>", lambda e: self.chat_display.config(cursor="hand2"))
                    self.chat_display.tag_bind(toggle_tag, "<Leave>", lambda e: self.chat_display.config(cursor=""))
                    
                    break
                    
        except Exception as e:
            self.add_message(f"切换过程中发生错误: {e}")
        finally:
            self.chat_display.config(state=tk.DISABLED)
    
    def parse_inline_markdown(self, text):
        """解析行内Markdown格式"""
        import re
        
        # 解析粗体 **text** 或 __text__
        bold_pattern = r'\*\*(.*?)\*\*|__(.*?)__'
        text = re.sub(bold_pattern, r'**\1\2**', text)
        
        # 解析斜体 *text* 或 _text_
        italic_pattern = r'\*(.*?)\*|_(.*?)_'
        text = re.sub(italic_pattern, r'*\1\2*', text)
        
        # 解析行内代码 `code`
        code_pattern = r'`(.*?)`'
        text = re.sub(code_pattern, r'`\1`', text)
        
        return text
    
    def typewriter_effect(self, text, tag=None, delay_ms=50):
        """基础打字机效果"""
        if self.is_typing:
            return
        
        self.is_typing = True
        self.chat_display.config(state=tk.NORMAL)
        
        def type_char(index=0):
            if index < len(text) and self.is_typing:
                char = text[index]
                if tag:
                    self.chat_display.insert(tk.END, char, tag)
                else:
                    self.chat_display.insert(tk.END, char)
                
                self.chat_display.see(tk.END)
                self.chat_display.update_idletasks()
                
                # 动态延迟：标点符号稍长，空格稍短
                if char in '。！？.!?':
                    actual_delay = delay_ms * 3
                elif char in '，,；;：:':
                    actual_delay = delay_ms * 2
                elif char == ' ':
                    actual_delay = delay_ms // 2
                else:
                    actual_delay = delay_ms
                
                self.root.after(actual_delay, lambda: type_char(index + 1))
            else:
                self.is_typing = False
                self.chat_display.insert(tk.END, "\n\n")
                self.chat_display.see(tk.END)
                self.chat_display.config(state=tk.DISABLED)
        
        type_char()
    
    def typewriter_effect_with_markdown(self, text, tag=None, delay_ms=50):
        """支持Markdown格式的打字机效果"""
        if self.is_typing:
            return
        
        self.is_typing = True
        self.chat_display.config(state=tk.NORMAL)
        
        # 简单的markdown解析
        import re
        
        # 分割文本为段落和格式化片段
        segments = []
        current_pos = 0
        
        # 查找所有markdown格式
        patterns = [
            (r'\*\*(.*?)\*\*', 'bold'),  # 粗体
            (r'\*(.*?)\*', 'italic'),    # 斜体
            (r'`(.*?)`', 'code'),        # 行内代码
        ]
        
        all_matches = []
        for pattern, format_type in patterns:
            for match in re.finditer(pattern, text):
                all_matches.append((match.start(), match.end(), match.group(1), format_type))
        
        # 按位置排序
        all_matches.sort(key=lambda x: x[0])
        
        # 构建段落列表
        last_end = 0
        for start, end, content, format_type in all_matches:
            if start > last_end:
                segments.append((text[last_end:start], None))
            segments.append((content, format_type))
            last_end = end
        
        if last_end < len(text):
            segments.append((text[last_end:], None))
        
        def type_segments(seg_index=0, char_index=0):
            if seg_index >= len(segments) or not self.is_typing:
                self.is_typing = False
                self.chat_display.insert(tk.END, "\n\n")
                self.chat_display.see(tk.END)
                self.chat_display.config(state=tk.DISABLED)
                return
            
            segment_text, format_type = segments[seg_index]
            
            if char_index < len(segment_text):
                char = segment_text[char_index]
                
                # 根据格式类型选择标签
                if format_type == 'bold':
                    char_tag = 'markdown_bold'
                elif format_type == 'italic':
                    char_tag = 'markdown_italic'
                elif format_type == 'code':
                    char_tag = 'markdown_code'
                else:
                    char_tag = tag
                
                self.chat_display.insert(tk.END, char, char_tag)
                self.chat_display.see(tk.END)
                self.chat_display.update_idletasks()
                
                # 动态延迟
                if char in '。！？.!?':
                    actual_delay = delay_ms * 3
                elif char in '，,；;：:':
                    actual_delay = delay_ms * 2
                elif char == ' ':
                    actual_delay = delay_ms // 2
                else:
                    actual_delay = delay_ms
                
                self.root.after(actual_delay, lambda: type_segments(seg_index, char_index + 1))
            else:
                # 当前段落完成，移动到下一个段落
                self.root.after(delay_ms, lambda: type_segments(seg_index + 1, 0))
        
        # 配置markdown样式
        self.chat_display.tag_configure('markdown_bold', font=('Consolas', 10, 'bold'))
        self.chat_display.tag_configure('markdown_italic', font=('Consolas', 10, 'italic'))
        self.chat_display.tag_configure('markdown_code', font=('Consolas', 9), background='#f0f0f0')
        
        type_segments()
    
    def set_typing_status(self, is_typing):
        """设置打字状态"""
        self.is_typing = is_typing
    
    def get_input_text(self):
        """获取输入文本"""
        return self.input_text.get(1.0, tk.END).strip()
    
    def clear_input(self):
        """清空输入框"""
        self.input_text.delete(1.0, tk.END)
    
    def get_model_var(self):
        """获取模型变量"""
        return self.model_var
    
    def get_thinking_var(self):
        """获取思考变量"""
        return self.thinking_var
    
    def get_chat_history(self):
        """获取聊天历史"""
        return self.chat_history.copy()
    
    def set_chat_history(self, history: List[Dict[str, str]]):
        """设置聊天历史"""
        self.chat_history = history.copy()
    
    def add_to_history(self, role: str, content: str):
        """添加消息到历史记录"""
        self.chat_history.append({"role": role, "content": content})
    
    def load_conversation(self, messages: List[Dict[str, str]]):
        """加载对话到聊天界面"""
        # 清空当前聊天
        self.clear_chat()
        
        # 设置聊天历史
        self.set_chat_history(messages)
        
        # 显示历史消息
        for msg in messages:
            role = msg.get("role", "user")
            content = msg.get("content", "")
            
            if role == "system":
                self.add_message(content, "system")
            elif role == "user":
                self.add_message(content, "user")
            elif role == "assistant":
                self.add_message(content, "assistant")
    
    def _on_discussion_click(self):
        """讨论按钮点击事件"""
        # 获取当前输入内容作为讨论主题
        topic = self.get_input_text()
        if not topic:
            self.add_message("请输入讨论主题！", "system")
            return
        
        # 打开讨论配置对话框
        dialog = DiscussionDialog(self.root, self.models, self._on_discussion_config_confirm)
    
    def _on_discussion_config_confirm(self, config):
        """讨论配置确认回调"""
        # 获取讨论主题
        topic = self.get_input_text()
        
        # 触发讨论开始回调
        if self.on_start_discussion:
            self.on_start_discussion(topic, config)
        
        # 显示讨论开始消息
        self.add_message(f"🤖 开始AI讨论: {topic}", "system")
        self.add_message("💬 讨论进行中... 点击'查看讨论进度'按钮查看详细过程", "system")
        
        # 添加查看讨论进度按钮
        self._add_discussion_progress_button()
    
    def _add_discussion_progress_button(self):
        """添加查看讨论进度按钮"""
        self.chat_display.config(state=tk.NORMAL)
        
        # 创建唯一标签
        button_tag = f"discussion_button_{int(time.time())}"
        
        # 添加按钮
        self.chat_display.insert(tk.END, "\n")
        self.chat_display.insert(tk.END, "📊 查看讨论进度", button_tag)
        self.chat_display.insert(tk.END, "\n\n")
        
        # 配置按钮样式
        self.chat_display.tag_configure(button_tag, 
                                      foreground="#28a745", 
                                      background="#f8f9fa",
                                      relief=tk.RAISED, 
                                      borderwidth=1,
                                      font=('Microsoft YaHei', 10, 'bold'),
                                      justify=tk.CENTER)
        
        # 绑定点击事件
        self.chat_display.tag_bind(button_tag, "<Button-1>", self._on_view_discussion_progress)
        self.chat_display.tag_bind(button_tag, "<Enter>", lambda e: self.chat_display.config(cursor="hand2"))
        self.chat_display.tag_bind(button_tag, "<Leave>", lambda e: self.chat_display.config(cursor=""))
        
        self.chat_display.config(state=tk.DISABLED)
    
    def _on_view_discussion_progress(self, event=None):
        """查看讨论进度按钮点击事件"""
        if self.on_view_discussion_progress:
            self.on_view_discussion_progress()

    def _on_context_cache_toggle(self):
        """上下文缓存开关切换事件"""
        use_cache = self.context_cache_var.get()
        context_manager.set_use_cache(use_cache)
        status = "启用" if use_cache else "禁用"
        self.add_message(f"上下文缓存已{status}", "system")

    def _on_max_tokens_change(self):
        """最大上下文tokens变更事件"""
        max_tokens = self.max_context_tokens_var.get()
        context_manager.set_max_tokens(max_tokens)
        self.add_message(f"最大上下文tokens已设置为: {max_tokens}", "system")

    def _on_max_messages_change(self):
        """最大上下文消息数变更事件"""
        max_messages = self.max_context_messages_var.get()
        context_manager.set_max_messages(max_messages)
        self.add_message(f"最大上下文消息数已设置为: {max_messages}", "system")

    def set_context_callbacks(self, on_context_cache_change: Callable[[bool], None] = None,
                            on_max_tokens_change: Callable[[int], None] = None,
                            on_max_messages_change: Callable[[int], None] = None):
        """设置上下文管理回调函数"""
        self.on_context_cache_change = on_context_cache_change
        self.on_max_tokens_change = on_max_tokens_change
        self.on_max_messages_change = on_max_messages_change